package com.pine.dcts.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pine.dcts.common.DctsConstant;
import com.pine.dcts.common.DctsException;
import com.pine.dcts.entity.Role;
import com.pine.dcts.entity.RoleUser;
import com.pine.dcts.mapper.RoleMapper;
import com.pine.dcts.mapper.RoleUserMapper;
import com.pine.dcts.query.RoleQuery;
import com.pine.dcts.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
    @Autowired
    private RoleUserMapper roleUserMapper;
    @Override
    public List<String> getListByUserId(Integer userId) {
        return this.baseMapper.getRoleCodesByUserId(userId);
    }

    @Override
    public IPage<Role> selectPage(RoleQuery query) {
        Page page = query.getPage();
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(Role::getId);
        return page(page,wrapper);
    }

    @Override
    public List<Role> getList() {
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getStatus, DctsConstant.YES);
        return list(wrapper);
    }

    @Override
    public List<Integer> getRoleIdsByUserId(Integer userId) {
        LambdaQueryWrapper<RoleUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleUser::getUserId,userId);
        List<RoleUser> roleUsers = this.roleUserMapper.selectList(wrapper);
        return roleUsers.stream().map(RoleUser::getRoleId).collect(Collectors.toList());
    }

    @Override
    public boolean validateRoleBind(Integer roleId) {
        LambdaQueryWrapper<RoleUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleUser::getRoleId,roleId);
        return this.roleUserMapper.selectCount(wrapper)>0;
    }

    @Override
    public void deleteRoleBindByRoleId(Integer roleId) {
        LambdaQueryWrapper<RoleUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleUser::getRoleId,roleId);
        this.roleUserMapper.delete(wrapper);
    }

    @Override
    public void deleteRoleBindByUserId(Integer userId) {
        LambdaQueryWrapper<RoleUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RoleUser::getUserId,userId);
        this.roleUserMapper.delete(wrapper);
    }

    @Override
    public void bindRoleUser(Integer userId, Integer[] roleId) {
        deleteRoleBindByUserId(userId);
        for(Integer id:roleId){
            RoleUser roleUser = new RoleUser();
            roleUser.setRoleId(id);
            roleUser.setUserId(userId);
            this.roleUserMapper.insert(roleUser);
        }
    }

    @Transactional
    @Override
    public boolean save(Role entity) {
        if(!check(entity)){
            throw new DctsException("该角色编码已存在");
        }
        entity.setStatus(DctsConstant.YES);
        return super.save(entity);
    }

    @Transactional
    @Override
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        idList.forEach(id->{
            if(this.validateRoleBind(Integer.valueOf((String) id))){
                throw new DctsException("该角色已被授权，无法删除");
            }
            //移除已授权的角色
            this.deleteRoleBindByRoleId(Integer.valueOf((String) id));
            //移除角色信息
            this.removeById(id);
        });
        return true;
    }
    @Transactional
    @Override
    public boolean updateById(Role entity) {
        if(!check(entity)){
            throw new DctsException("该角色编码已存在");
        }
        return super.updateById(entity);
    }

    /**
     * 检查配置项是否有重复
     *
     * @param entity
     * @return
     */
    private boolean check(Role entity) {
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Role::getCode, entity.getCode());
        if (entity.getId() != null) {
            wrapper.ne(Role::getId, entity.getId());
        }
        return this.count(wrapper) == 0;
    }


}
